#include "socket.hpp"
#include "protocol.hpp"
#include "task.hpp"

class TcpServer
{
public:
    TcpServer(uint16_t port, const std::string ip = IP)
        : _socket(port, ip),
          _islisten(false)
    {
    }

    void Init()
    {
        bool ret = _socket.Init();
        if (ret == false)
        {
            exit(1);
        }

        ret = _socket.Bind();
        if (ret == false)
        {
            exit(1);
        }
        // 设置为listen状态
        ret = _socket.Listen();
        if (ret == false)
        {
            exit(1);
        }
        _islisten = true;
    }

    void Run()
    {
        std::cout << "Server running..." << std::endl;
        while (_islisten)
        {
            sockaddr_in client_addr;
            socklen_t len = sizeof(client_addr);
            int fd = _socket.Accept(client_addr, len);
            if (fd < 0)
            {
                continue;
            }
            std::cout << "get a new connection, ip : " << inet_ntoa(client_addr.sin_addr) << ", port :"
                      << ntohs(client_addr.sin_port) << std::endl;
            // 处理新连接
            std::string msg;
            int ReadSize = _socket.Recv(fd, msg);
            if (ReadSize < 0)
            {
                continue;
            }
            else if (ReadSize == 0)
            {
                std::cout << "Client quit..." << std::endl;
                close(fd);
                continue;
            }
            // std::cout << "Client say: " << msg << std::endl;
            // std::string ret = Service(fd, msg);

            std::string ret = Service(msg);

            int WriteSize = _socket.Send(fd, ret);
            if (WriteSize < 0)
            {
                continue;
            }
        }
    }

    std::string Service(std::string &msg)
    {
        // 解码
        std::string request = Decode(msg);
        // 创造一个请求对象
        Request req;
        // 反序列化
        req.Deserialize(request);
        // 调用计算函数
        Response res = Calc(&req);
        // 序列化结果
        std::string ret = res.Serialize();
        return ret;
    }

private:
    TcpSocket _socket;
    bool _islisten;
};